
static char RCSId[]="$Id: DataPane.m,v 1.1.1.1 1993/03/18 03:31:34 davis Exp $";


#import <appkit/Application.h>
#import <appkit/Box.h>
#import <appkit/Form.h>
#import <appkit/OpenPanel.h>
#import <appkit/View.h>

#import <sys/param.h>			/* MAXPATHLEN                   */

#import "CellScrollView.h"
#import "DataPane.h"
#import "FunctionObject.h"
#import "MultipleSelectionMatrix.h"
#import "Status.h"
#import "SubCell.h"


@interface DataPane (Private)

- _updateFunctionsMatrix;
- _updateControlsForSelectedFunction;

@end


@implementation DataPane


- init
{
    [super init];

    [NXApp loadNibSection: "DataPane.nib"
		    owner: self
		withNames: NO
		 fromZone: [self zone]];

    view = [window setContentView:[[View alloc] init]];
    icon = "InspectorData.tiff";
    functionObjects = nil;


    /*  Initialize the CellScrollView of functions  */

    [functionsScrollView initMatrix:[SubCell class]];
    functionsMatrix = [functionsScrollView cellMatrix];
    [[functionsMatrix setAction:@selector(selectFunction:)] setTarget:self];

    return self;
}


/*  
 *  Overridden from Pane.
 */
- selectControl:sender
{
    [functionsForm selectTextAt:0];
    return self;
}


- updateStatus:aStatus doc:aDoc
{
    id oldStatus = status;

    /*  
     *  We only bother updating if status has changed since we last 
     *  updated, or if we just became the current pane (didSwap) -- 
     *  assuming that status and aDoc are non-nil, of course.
     */

    if ([super updateStatus:aStatus doc:aDoc]
	&& ((status != oldStatus) || didSwap)) {

	Window *viewWindow;

	[(viewWindow = [view window]) disableDisplay];

	functionObjects = [status functions];

	[dummyFormCellX setStringValue:[status dummyVar:X_TAG]];
	[dummyFormCellY setStringValue:[status dummyVar:Y_TAG]];
	[dummyFormCellY setEnabled:[status isThreeD]];
	[self _updateFunctionsMatrix];

	if (![functionsMatrix selectedCell])
	    [functionsMatrix selectCellAt:0:0];
	[self _updateControlsForSelectedFunction];

	[viewWindow reenableDisplay];

	[self perform:@selector(selectControl:)
		 with:self
	   afterDelay:1
       cancelPrevious:YES];

	didSwap = NO;
	return self;

    }

    return nil;
}


- didSwapIn:sender
{
    didSwap = YES;
    return self;
}



- doSetDummy:sender
{
    [status setDummyVar:[sender tag] to:[sender stringValue]];
    return self;
}


- findDataFile:sender
{
    const char *const *files;
    id openPanel;
    char fullName[MAXPATHLEN];

    openPanel = [[OpenPanel new] allowMultipleFiles:YES];

    if ([openPanel runModalForTypes:NULL])
        for (files = [openPanel filenames]; files && *files; files++) {

            sprintf (fullName, "%s/%s", [openPanel directory], *files);
            [self addDataFile:fullName];

        }

    return self;
}


- selectFunction:sender
{
    if (![functionsMatrix selectedCell])
	[functionsMatrix selectCellAt:0:0];
    else {
	[self _updateControlsForSelectedFunction];
	[functionsForm selectTextAt:0];
    }

    return self;
}


- deleteSelectedFunctions:sender
{
    int i;
    int maxrow = [functionsMatrix cellCount] - 1;
    int row = [functionsMatrix selectedRow];
    int col = [functionsMatrix selectedCol];

    for (i = maxrow; i >= 0; i--) {
        SubCell *cell = [functionsMatrix cellAt:i:0];
        if ([cell isHighlighted]) {
            /*
             * If a cell is highlighted, remove (and free) the corresponding
             * item from the list of SubObjects.
             */
            [[functionObjects removeObject:[cell subObject]] free];
	    maxrow--;
        }
    }

    [functionsScrollView loadCellsFrom:functionObjects];

    [functionsMatrix selectCellAt:(row > maxrow)? maxrow:row :col];
    [functionsMatrix scrollCellToVisible:(row > maxrow)? maxrow:row :col];
    [self selectFunction:self];

    /*  
     *  We change the list of functions maintainted by Status without 
     *  going through Status, so we need to make sure the changes are 
     *  noticed. 
     */
    [status reportSettingsChange:self];

    return self;
}


- modifySelectedFunction:sender
{
    id cell = [functionsMatrix selectedCell];

    [[cell subObject] setStringValue: [functionsForm stringValue]];
    [functionsScrollView loadCellsFrom:functionObjects];
    [functionsMatrix selectCell:cell];
    [self selectFunction:self];

    [status reportSettingsChange:self];
    return self;
}


- addFunction:sender
{
    const char *stringValue;
    int count;
    FunctionObject *functionObject;

    stringValue = [functionsForm stringValue];

    if (![FunctionObject isAcceptableStringValue:stringValue])  {
        [self selectFunction:self];
        return nil;
    }

    functionObject = [[FunctionObject allocFromZone: [self zone]]
                                     initFromString: stringValue];
    [functionObjects addObject:functionObject];
    [functionsScrollView loadCellsFrom:functionObjects];
  /*
   *  Assumptions in this next line:
   *    There are as many SubCells as there are functionObjects
   *    We've added the new functionObject at the end of the list.
   *    We want to display the functionObject we just added and highlight it.
   *  In short, this is a hack.
   *                                    -- CellScrollView, NeXT Example
   */
    count = [functionObjects count] - 1;
    [functionsMatrix scrollCellToVisible:count :0];
    [functionsMatrix selectCellAt:count:0];
    [self selectFunction:self];

    [status reportSettingsChange:self];

    return self;
}


- setFunctionTitle:sender
{
    int i;
    SubCell *cell;
    BOOL didChange = NO;

    for (i = [functionsMatrix cellCount] - 1 ; i >= 0 ; i--) {
        cell = [functionsMatrix cellAt:i:0];
        if ([cell isHighlighted])  {
            [[cell subObject] setTitle: [sender stringValue]];
            didChange = YES;
        }
    }

    if (didChange)
        [status reportSettingsChange:self];

    return self;
}


- setFunctionStyle:sender
{
    int i;
    SubCell *cell;
    BOOL didChange = NO;
    id oldstatus = status;

    for (i = [functionsMatrix cellCount] - 1 ; i >= 0 ; i--) {
        cell = [functionsMatrix cellAt:i:0];
        if ([cell isHighlighted])  {
            [[cell subObject] setStyle: [sender selectedTag]];
            didChange = YES;
        }
    }

    if (didChange)
        [status reportSettingsChange:self];

    [self selectFunction:self];

    return self;
}


- setFunctionPointsStyle:sender
{
    int i;
    SubCell *cell;
    BOOL didChange = NO;

    for (i = [functionsMatrix cellCount] - 1 ; i >= 0 ; i--) {
        cell = [functionsMatrix cellAt:i:0];
        if ([cell isHighlighted])  {
            [[cell subObject] setPointsStyle: [sender selectedTag]];
            didChange = YES;
        }
    }

    if (didChange)
        [status reportSettingsChange:self];

    return self;
}


- setFunctionLineStyle:sender
{
    int i;
    SubCell *cell;
    BOOL didChange = NO;

    for (i = [functionsMatrix cellCount] - 1 ; i >= 0 ; i--) {
        cell = [functionsMatrix cellAt:i:0];
        if ([cell isHighlighted])  {
            [[cell subObject] setLineStyle: [sender selectedTag]];
            didChange = YES;
        }
    }

    if (didChange)
        [status reportSettingsChange:self];

    return self;
}



- addDataFile:(const char *)aPath
{
    int count;

    [doc addDataFile:aPath];
    [functionsScrollView loadCellsFrom:functionObjects];

    /*
     * Assumptions in this next line:
     *    There are as many SubCells as there are functionObjects
     *    We've added the new functionObject at the end of the list.
     *    We want to display the functionObject we just added and highlight it.
     * In short, this is a hack.
     *                          -- CellScrollView, NeXT Example
     */
    count = [functionObjects count] - 1;
    [functionsMatrix scrollCellToVisible:count :0];
    [functionsMatrix selectCellAt:count:0];
    [self selectFunction:self];

    return self;
}



// Shuts up the compiler about unused RCSId
- (const char *) rcsid
{
    return RCSId;
}


@end


@implementation DataPane (Private)


- _updateFunctionsMatrix
{
    int functionCount, counter = 0;
    int fieldcount;
    int row = [functionsMatrix selectedRow];
    int col = [functionsMatrix selectedCol];

    [functionsScrollView loadCellsFrom:functionObjects];
    if (functionCount = [functionObjects count]) {
        for (counter = 0; counter < functionCount; counter++)
            [[functionsMatrix cellAt:counter:0]
                             setStringValue:[[functionObjects objectAt:counter]
                                             stringValue]];
    }

    fieldcount = [functionsMatrix cellCount];
    while (counter < fieldcount)
        [[functionsMatrix cellAt:counter++:0] setStringValue:""];

    [functionsMatrix selectCellAt:(row > fieldcount)? fieldcount:row :col];

    return self;
}


- _updateControlsForSelectedFunction
{
    int style = FUNCTION_NOSTYLE;
    BOOL enabled;
    BOOL multiple = [functionsMatrix multipleCellsSelected];
    FunctionObject *f = [[functionsMatrix selectedCell] subObject];
    Window *viewWindow;
    Box *aBox;

    [(viewWindow = [view window]) disableDisplay];

    if (!multiple && f) {

	[functionsForm setStringValue: [f stringValue]];
	[functionsTitleField setStringValue: [f title]];

	[functionsStyleMatrix selectCellWithTag: style = [f style]];
	[pointsStyleMatrix selectCellWithTag: [f pointsStyle]];
	[lineStyleMatrix selectCellWithTag: [f lineStyle]];

    } else {

	[functionsForm setStringValue: ""];
	[functionsStyleMatrix selectCellWithTag: FUNCTION_NOSTYLE];
	[pointsStyleMatrix selectCellWithTag: POINTS_NOSTYLE];
	[lineStyleMatrix selectCellWithTag: LINE_NOSTYLE];

    }


    [deleteFunctionButton setEnabled:f? YES: NO];
    [modifyFunctionButton setEnabled:f? !multiple: NO];
    [functionsTitleField setEnabled: f? !multiple: NO];

    [functionsStyleMatrix setEnabled:f? !multiple: NO];

    [pointsStyleMatrix setEnabled:enabled = (f && !multiple &&
	     ((style == FUNCTION_POINTS) || (style == FUNCTION_LINESPOINTS)))];
    [pointsStyleLabel setEnabled:enabled];

    [lineStyleMatrix setEnabled:enabled = (f && !multiple &&
	      ((style == FUNCTION_LINES) || (style == FUNCTION_LINESPOINTS)))];
    [lineStyleLabel setEnabled:enabled];

    enabled = [[aBox = [[functionsStyleMatrix superview] superview] cell]
	       isEnabled];
    if (enabled != (f? !multiple: NO))
	[[aBox cell] setEnabled: f? !multiple: NO];

    [viewWindow reenableDisplay];
    [view display];

    return self;
}


@end
